package com.example.socket.core;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;

import static com.example.socket.core.MessageConstant.STATE_RESPONSE;

/**
 * 信息头<br/>
 * 格式:[长度][会话][序号][状态][模块号][指令]
 */
public class Header {

    /** 默认消息头长度 */
    public static final int DEFAULT_HEADER_LENGTH = 23;
    /**消息类型*/
    private byte type;
    /** 状态 */
    private short state;
    /** 序号 */
    private int sn;
    /** 会话标识 */
    private long session;
    /** 指令 */
    private Command command;

    public static Header valueOf(ByteBuf buff) {
        byte type = buff.readByte();
        Header result = new Header();
        result.type = type;
        result.read(buff);
        return result;
    }

    public static Header valueOf(byte type, short state, int sn, long session, Command command) {
        Header result = new Header();
        result.type = type;
        result.state = state;
        result.sn = sn;
        result.session = session;
        result.command = command;
        return result;
    }

    protected void read(ByteBuf buff) {
        this.session = buff.readLong();
        this.sn = buff.readInt();
        this.state = buff.readShort();
        this.command = Command.valueOf(buff);
    }

    /**
     * 将信息头转换为 byte[] 表示格式
     */
    public byte[] toBytes(int length) {
        ByteBuf buffer = Unpooled.buffer(getSize());
        write(buffer, length);
        // 更新正确的长度并返回
        byte[] bytes = new byte[getSize()];
        buffer.readBytes(bytes);
        return bytes;
    }

    /**
     * 将信息头转换为 byte[] 表示格式
     */
    public ByteBuf toBytes(ByteBufAllocator alloc, int length) {
        ByteBuf buffer = alloc.buffer(getSize());
        write(buffer, length);
        // 更新正确的长度并返回
        return buffer;
    }

    protected void write(ByteBuf buffer, int length) {
        //写数据到buffer
        buffer.writeInt(length);
        buffer.writeByte(type);
        buffer.writeLong(session);
        buffer.writeInt(sn);
        buffer.writeShort(state);
        buffer.writeBytes(command.toBytes());
    }

    @JsonIgnore
    public int getSize() {
        return DEFAULT_HEADER_LENGTH;
    }

    public Header copy() {
        return Header.valueOf((byte) 0, state, sn, session, command);
    }

    @Override
    public String toString() {
        return "[T=" + type + ",ST=" + state + ", SN=" + sn + ", IO=" + session + ", C=" + command + "]";
    }
    // 状态处理方法

    /**
     * 检查状态值中是否有指定状态
     * @param state 状态值
     * @param check 被检查的状态
     * @return
     */
    public static boolean hasState(int state, int check) {
        return (state & check) == check ? true : false;
    }

    /**
     * 添加状态
     * @param added 被添加的状态
     */
    public void addState(short added) {
        state = (short) (state | added);
    }

    /**
     * 移除状态
     * @param removed 被移除的状态
     */
    public void removeState(short removed) {
        state = (short) (state ^ removed);
    }

    /**
     * 检查是否有指定状态
     * @param check 被检查的状态
     * @return
     */
    public boolean hasState(short check) {
        return hasState(state, check);
    }

    /**
     * 是否回应信息
     * @return
     */
    @JsonIgnore
    public boolean isResponse() {
        return hasState(state, STATE_RESPONSE);
    }

    // Getter and Setter ...

    public short getState() {
        return state;
    }

    public void setState(short state) {
        this.state = state;
    }

    public int getSn() {
        return sn;
    }

    public void setSn(int sn) {
        this.sn = sn;
    }

    public long getSession() {
        return session;
    }

    public void setSession(long session) {
        this.session = session;
    }

    public Command getCommand() {
        return command;
    }

    public void setCommand(Command command) {
        this.command = command;
    }

    public byte getType() {
        return type;
    }

    public void setType(byte type) {
        this.type = type;
    }
}